﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Windows.Forms;
using HWorld.Networking;
using OClick;
using OClick.OCR.Tesseract;
using ROrganizer.Client;
using ROrganizer.Client.Crawling;
using ROrganizer.UI.Controllers.Core;
using NCore;

namespace ROrganizer.UI.Controllers
{
    internal class CrawlerFormController
    {
        private readonly FastObservableCollection<Message> messages;
        private readonly Crawler crawler;

        public CrawlerFormController()
        {
            var session = new HNetworkSession();
            var oclick = new OFacade(
                assembly: Assembly.Load("OClick.Providers"),
                ocr: new TesseractRecognizer(
#if !DEBUG
                datapath: Path.Combine(Environment.CurrentDirectory, "tessdata")
#endif
                ), logger: new OClickLogger { Adder = this.LogOClick });

            this.messages = new FastObservableCollection<Message>();
            this.crawler = new Crawler(oclick, session, logger: new CrawlerLogger { Adder = this.LogCrawler });
            this.crawler.Changed += (sender, args) => this.OnChanged();

            this.Index = "0";
            this.Count = "20";
        }

        public event EventHandler Changed;
        private void OnChanged()
        {
            if (this.Changed != null)
                this.Changed(this, EventArgs.Empty);
        }

        public string Url { get; set; }
        public string Index { get; set; }
        public string Count { get; set; }

        public ObservableCollection<Message> Messages
        {
            get { return this.messages; }
        }

        public bool CanStop()
        {
            return this.crawler.IsWorking;
        }

        public void Stop()
        {
            this.crawler.Stop();
        }

        public bool CanStart()
        {
            int dummy;

            return Uri.IsWellFormedUriString(this.Url, UriKind.Absolute)
                && Int32.TryParse(this.Index, out dummy)
                && Int32.TryParse(this.Count, out dummy)
                && !this.crawler.IsWorking;
        }

        public void Start(IWin32Window owner)
        {
            this.crawler.Start(this.Url, Int32.Parse(this.Index), Int32.Parse(this.Count));
        }

        public void ShowAbout(IWin32Window owner)
        {
            ViewManager.ShowAbout(owner);
        }

        public void ShowResults(IWin32Window owner)
        {
            ViewManager.ShowResultsManager(owner);
        }

        public void ShowSettings(IWin32Window owner)
        {
            ViewManager.ShowCrawlerSettings(owner);
        }

        private void LogOClick(string message)
        {
            this.messages.Add(new Message { Source = "OClick", Content = message });
        }

        private void LogCrawler(string message)
        {
            this.messages.Add(new Message { Source = "Crawler", Content = message });
        }

        public class Message
        {
            public string Source { get; set; }
            public string Content { get; set; }
        }

        private class OClickLogger : OLogger
        {
            public Action<string> Adder { get; set; }

            public override void Push(Guid provider, string format, params object[] parameters)
            {
                if (this.Adder != null)
                    this.Adder(String.Format(format, parameters));
            }
        }

        private class CrawlerLogger : Logger
        {
            public Action<string> Adder { get; set; }

            public override void OnLog(Guid message, string format, params object[] parameters)
            {
                if (this.Adder != null)
                    this.Adder(String.Format(format, parameters));
            }
        }
    }
}
